package com.foton.logistic.daemon;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.IBinder;

import com.foton.logistic.util.tool.LogUtil;

import java.util.concurrent.TimeUnit;

import rx.Observable;
import rx.Subscription;
import rx.functions.Action1;

public class WatchDogService extends Service {

    protected static final int HASH_CODE = 2;

    //定时
    protected static Subscription sSubscription;
    protected static PendingIntent sPendingIntent;

    /**
     * 守护服务，运行在:watch子进程中
     */
    protected final int onStart(Intent intent, int flags, int startId) {

        try {
            LogUtil.e("--------------starting WatchDogService--------------" + DaemonEnv.sInitialized);
            if (!DaemonEnv.sInitialized) {
                return START_STICKY;
            }

            //启动前台服务而不显示通知的漏洞已在 API Level 25 修复！
            if (Build.VERSION.SDK_INT <= DaemonEnv.SDKVERSION) {
                startForeground(HASH_CODE, new Notification());
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
                    startService(new Intent(DaemonEnv.sApp, WatchDogNotificationService.class));
            }

            //已订阅且未取消订阅
            if (sSubscription != null && !sSubscription.isUnsubscribed()){
                return START_STICKY;
            }

            //定时检查 AbsWorkService 是否在运行，如果不在运行就把它拉起来
            //Android 5.0+ 使用 JobScheduler，效果比 AlarmManager 好
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                KeepLiveManager.getInstance().startJobScheduler();
            } else {
                sPendingIntent = KeepLiveManager.getInstance().startAlarm();
            }

            //使用定时 Observable，避免 Android 定制系统 JobScheduler / AlarmManager 唤醒间隔不稳定的情况
            sSubscription = Observable.interval(DaemonEnv.getWakeUpInterval(), TimeUnit.MILLISECONDS)
                    .subscribe(new Action1<Long>() {
                        public void call(Long aLong) {
                            WatchDogService.this.startService(new Intent(DaemonEnv.sApp, DaemonEnv.sServiceClass));
                        }
                    }, new Action1<Throwable>() {
                        public void call(Throwable t) {
                            t.printStackTrace();
                        }
                    });

            //守护 Service 组件的启用状态, 使其不被 MAT 等工具禁用
            getPackageManager().setComponentEnabledSetting(new ComponentName(getPackageName(), DaemonEnv.sServiceClass.getName()),
                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
            LogUtil.e("--------------start WatchDogService success--------------");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return START_STICKY;
    }

    @Override
    public final int onStartCommand(Intent intent, int flags, int startId) {
        return onStart(intent, flags, startId);
    }

    @Override
    public final IBinder onBind(Intent intent) {
        onStart(intent, 0, 0);
        return null;
    }

    protected void onEnd(Intent rootIntent) {
        try {
            if (!DaemonEnv.sInitialized) {
                return;
            }
            startService(new Intent(DaemonEnv.sApp, DaemonEnv.sServiceClass));
            startService(new Intent(DaemonEnv.sApp, WatchDogService.class));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 最近任务列表中划掉卡片时回调
     */
    @Override
    public void onTaskRemoved(Intent rootIntent) {
        onEnd(rootIntent);
    }

    /**
     * 设置-正在运行中停止服务时回调
     */
    @Override
    public void onDestroy() {
        onEnd(null);
    }

    /**
     * 用于在不需要服务运行的时候取消 Job / Alarm / Subscription.
     *
     * 因 WatchDogService 运行在 :watch 子进程, 请勿在主进程中直接调用此方法.
     * 而是向 WakeUpReceiver 发送一个 Action 为 WakeUpReceiver.ACTION_CANCEL_JOB_ALARM_SUB 的广播.
     */
    public static void cancelJobAlarmSub() {
        try {
            if (!DaemonEnv.sInitialized) {
                return;
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                JobScheduler scheduler = (JobScheduler) DaemonEnv.sApp.getSystemService(JOB_SCHEDULER_SERVICE);
                scheduler.cancel(HASH_CODE);
            } else {
                AlarmManager am = (AlarmManager) DaemonEnv.sApp.getSystemService(ALARM_SERVICE);
                if (sPendingIntent != null) am.cancel(sPendingIntent);
            }
            if (sSubscription != null) {
                sSubscription.unsubscribe();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static class WatchDogNotificationService extends Service {

        /**
         * 利用漏洞在 API Level 18 及以上的 Android 系统中，启动前台服务而不显示通知
         * 运行在:watch子进程中
         */
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            try {
                startForeground(WatchDogService.HASH_CODE, new Notification());
                stopSelf();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return START_STICKY;
        }

        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }
}
